<template>
  <div class="particle-container" ref="particleContainer">
    <!-- Canvas 支持时显示粒子动画 -->
    <canvas 
      v-if="canvasSupported && !hasCanvasError" 
      ref="canvas" 
      class="particle-canvas"
    ></canvas>
    
    <!-- Canvas 不支持或出错时的降级方案 -->
    <div 
      v-else 
      class="fallback-background"
      :class="{ 'error-state': hasCanvasError }"
    >
      <!-- 静态背景效果 -->
      <div class="static-particles">
        <div 
          v-for="n in fallbackParticleCount" 
          :key="n"
          class="static-particle"
          :style="getStaticParticleStyle(n)"
        ></div>
      </div>
      
      <!-- 错误提示（仅在开发模式下显示） -->
      <div v-if="hasCanvasError && isDevelopment" class="canvas-error-info">
        <p>Canvas 渲染出现问题，已切换到静态背景</p>
        <small>{{ canvasErrorMessage }}</small>
      </div>
    </div>
  </div>
</template>

<script>
import { COLORS, PARTICLE } from '@/config/constants.js'
import { getDeviceInfo, getRecommendedAnimationConfig, isMobileDevice, getDevicePerformance } from '@/utils/deviceDetection.js'

export default {
  name: 'ParticleBackground',
  props: {
    maxParticles: {
      type: Number,
      default: 50
    },
    enablePerformanceOptimization: {
      type: Boolean,
      default: true
    }
  },
  data() {
    const deviceInfo = getDeviceInfo()
    const animationConfig = getRecommendedAnimationConfig()
    
    return {
      canvas: null,
      ctx: null,
      offscreenCanvas: null,
      offscreenCtx: null,
      useOffscreenCanvas: false,
      particles: [],
      animationId: null,
      mouse: { x: 0, y: 0 },
      particleCount: 50,
      throttleTimer: null,
      throttleDelay: 16, // 约60fps的节流延迟
      devicePerformance: 'medium', // low, medium, high
      canvasSupported: true,
      hasCanvasError: false,
      canvasErrorMessage: '',
      fallbackParticleCount: 20,
      staticParticles: [],
      isDevelopment: process.env.NODE_ENV === 'development',
      deviceInfo,
      animationConfig,
      isMobile: isMobileDevice(),
      reducedMotion: window.matchMedia('(prefers-reduced-motion: reduce)').matches
    }
  },
  mounted() {
    this.detectCanvasSupport()
    
    // 如果用户偏好减少动画，直接使用降级方案
    if (this.reducedMotion) {
      this.canvasSupported = false
      this.initFallbackBackground()
      return
    }
    
    if (this.canvasSupported) {
      this.applyDeviceOptimizations()
      this.initCanvas()
      this.createParticles()
      this.animate()
      this.handleResize()
      window.addEventListener('resize', this.handleResize)
      
      // 移动设备减少鼠标事件监听
      if (!this.isMobile) {
        window.addEventListener('mousemove', this.handleMouseMove)
      }
    } else {
      this.initFallbackBackground()
    }
  },
  beforeUnmount() {
    if (this.animationId) {
      cancelAnimationFrame(this.animationId)
    }
    if (this.throttleTimer) {
      clearTimeout(this.throttleTimer)
    }
    window.removeEventListener('resize', this.handleResize)
    window.removeEventListener('mousemove', this.handleMouseMove)
  },
  methods: {
    initCanvas() {
      try {
        this.canvas = this.$refs.canvas
        if (!this.canvas) {
          throw new Error('Canvas 元素未找到')
        }
        
        this.ctx = this.canvas.getContext('2d')
        if (!this.ctx) {
          throw new Error('无法获取 2D 渲染上下文')
        }
        
        // 检测并初始化 OffscreenCanvas
        this.initOffscreenCanvas()
        
        this.resizeCanvas()
      } catch (error) {
        this.handleCanvasError(error)
      }
    },
    
    initOffscreenCanvas() {
      // 检测 OffscreenCanvas 支持
      if (typeof OffscreenCanvas !== 'undefined' && this.devicePerformance !== 'low') {
        try {
          this.offscreenCanvas = new OffscreenCanvas(1, 1)
          this.offscreenCtx = this.offscreenCanvas.getContext('2d')
          this.useOffscreenCanvas = true
          console.log('OffscreenCanvas 已启用')
        } catch (error) {
          console.warn('OffscreenCanvas 初始化失败，使用常规 Canvas:', error)
          this.useOffscreenCanvas = false
        }
      } else {
        this.useOffscreenCanvas = false
      }
    },
    resizeCanvas() {
      const container = this.$refs.particleContainer
      const width = container.offsetWidth
      const height = container.offsetHeight
      
      this.canvas.width = width
      this.canvas.height = height
      
      // 同时调整 OffscreenCanvas 尺寸
      if (this.useOffscreenCanvas && this.offscreenCanvas) {
        this.offscreenCanvas.width = width
        this.offscreenCanvas.height = height
      }
    },
    handleResize() {
      this.resizeCanvas()
      this.particles = []
      this.createParticles()
    },
    handleMouseMove(event) {
      // 使用节流机制优化鼠标移动事件性能
      if (this.throttleTimer) {
        return
      }
      
      this.throttleTimer = setTimeout(() => {
        this.mouse.x = event.clientX
        this.mouse.y = event.clientY
        this.throttleTimer = null
      }, this.throttleDelay)
    },
    createParticles() {
      for (let i = 0; i < this.particleCount; i++) {
        this.particles.push({
          x: Math.random() * this.canvas.width,
          y: Math.random() * this.canvas.height,
          vx: (Math.random() - 0.5) * 2,
          vy: (Math.random() - 0.5) * 2,
          radius: Math.random() * 3 + 1,
          opacity: Math.random() * 0.5 + 0.2,
          originalOpacity: Math.random() * 0.5 + 0.2,
          color: this.getRandomColor()
        })
      }
    },
    getRandomColor() {
      return PARTICLE.COLORS[Math.floor(Math.random() * PARTICLE.COLORS.length)]
    },
    updateParticles() {
      this.particles.forEach(particle => {
        // 更新位置
        particle.x += particle.vx
        particle.y += particle.vy

        // 边界检测
        if (particle.x < 0 || particle.x > this.canvas.width) {
          particle.vx *= -1
        }
        if (particle.y < 0 || particle.y > this.canvas.height) {
          particle.vy *= -1
        }

        // 鼠标交互（使用动态交互范围）
        const dx = this.mouse.x - particle.x
        const dy = this.mouse.y - particle.y
        const distance = Math.sqrt(dx * dx + dy * dy)
        const interactionRange = this.interactionRange || 100
        
        if (distance < interactionRange) {
          const force = (interactionRange - distance) / interactionRange
          particle.vx += (dx / distance) * force * 0.1
          particle.vy += (dy / distance) * force * 0.1
          particle.opacity = Math.min(1, particle.originalOpacity + force)
        } else {
          particle.opacity = particle.originalOpacity
          particle.vx *= 0.99
          particle.vy *= 0.99
        }

        // 限制速度
        const maxSpeed = 3
        const speed = Math.sqrt(particle.vx * particle.vx + particle.vy * particle.vy)
        if (speed > maxSpeed) {
          particle.vx = (particle.vx / speed) * maxSpeed
          particle.vy = (particle.vy / speed) * maxSpeed
        }
      })
    },
    drawParticles() {
      if (this.useOffscreenCanvas && this.offscreenCtx) {
        // 使用 OffscreenCanvas 进行渲染
        this.renderToOffscreenCanvas()
        // 将 OffscreenCanvas 内容复制到主 Canvas
        this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)
        this.ctx.drawImage(this.offscreenCanvas, 0, 0)
      } else {
        // 使用常规 Canvas 渲染
        this.renderToMainCanvas()
      }
    },
    
    renderToOffscreenCanvas() {
      const ctx = this.offscreenCtx
      ctx.clearRect(0, 0, this.offscreenCanvas.width, this.offscreenCanvas.height)
      
      this.particles.forEach(particle => {
        ctx.beginPath()
        ctx.arc(particle.x, particle.y, particle.radius, 0, Math.PI * 2)
        ctx.fillStyle = particle.color + particle.opacity + ')'
        ctx.fill()
        
        // 根据设备性能决定是否添加发光效果
        if (this.enableGlowEffect !== false) {
          ctx.shadowBlur = 10
          ctx.shadowColor = particle.color + '0.5)'
          ctx.fill()
          ctx.shadowBlur = 0
        }
      })
      
      // 根据设备性能决定是否绘制连接线
      if (this.enableConnections !== false) {
        this.drawConnectionsToContext(ctx)
      }
    },
    
    renderToMainCanvas() {
      this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)
      
      this.particles.forEach(particle => {
        this.ctx.beginPath()
        this.ctx.arc(particle.x, particle.y, particle.radius, 0, Math.PI * 2)
        this.ctx.fillStyle = particle.color + particle.opacity + ')'
        this.ctx.fill()
        
        // 根据设备性能决定是否添加发光效果
        if (this.enableGlowEffect !== false) {
          this.ctx.shadowBlur = 10
          this.ctx.shadowColor = particle.color + '0.5)'
          this.ctx.fill()
          this.ctx.shadowBlur = 0
        }
      })
      
      // 根据设备性能决定是否绘制连接线
      if (this.enableConnections !== false) {
        this.drawConnectionsToContext(this.ctx)
      }
    },
    drawConnectionsToContext(ctx) {
      for (let i = 0; i < this.particles.length; i++) {
        for (let j = i + 1; j < this.particles.length; j++) {
          const dx = this.particles[i].x - this.particles[j].x
          const dy = this.particles[i].y - this.particles[j].y
          const distance = Math.sqrt(dx * dx + dy * dy)
          
          if (distance < 120) {
            const opacity = (120 - distance) / 120 * 0.3
            ctx.beginPath()
            ctx.moveTo(this.particles[i].x, this.particles[i].y)
            ctx.lineTo(this.particles[j].x, this.particles[j].y)
            ctx.strokeStyle = `${COLORS.PARTICLE_COLOR}${opacity})`
            ctx.lineWidth = 1
            ctx.stroke()
          }
        }
      }
    },
    applyDeviceOptimizations() {
      if (!this.enablePerformanceOptimization) {
        this.devicePerformance = 'high'
        this.adjustParticleCount()
        return
      }

      // 使用设备检测工具获取性能等级
      this.devicePerformance = getDevicePerformance()
      
      // 应用推荐的动画配置
      this.applyAnimationConfig()
      
      // 调整粒子数量
      this.adjustParticleCount()
      
      console.log(`设备性能等级: ${this.devicePerformance}`, {
        deviceInfo: this.deviceInfo,
        animationConfig: this.animationConfig,
        particleCount: this.particleCount
      })
    },
    
    applyAnimationConfig() {
      // 根据推荐配置调整动画参数
      const config = this.animationConfig
      
      // 调整帧率
      if (config.targetFPS <= 30) {
        this.throttleDelay = 33 // 30fps
      } else if (config.targetFPS <= 60) {
        this.throttleDelay = 16 // 60fps
      } else {
        this.throttleDelay = 8 // 120fps
      }
      
      // 根据设备类型调整交互范围
      this.interactionRange = this.isMobile ? 80 : 100
      
      // 低性能设备禁用某些效果
      this.enableGlowEffect = config.enableComplexEffects
      this.enableConnections = config.enableParticleConnections
    },
    
    adjustParticleCount() {
      const baseCount = this.maxParticles
      const config = this.animationConfig
      
      // 使用推荐配置中的粒子数量
      this.particleCount = Math.min(config.maxParticles, baseCount)
      
      // 移动设备进一步减少粒子数量
      if (this.isMobile) {
        this.particleCount = Math.floor(this.particleCount * 0.6)
      }
      
      // 确保最小粒子数量
      this.particleCount = Math.max(this.particleCount, 5)
      
      // 调整降级方案的粒子数量
      this.fallbackParticleCount = Math.floor(this.particleCount * 0.4)
    },
    
    animate() {
      try {
        this.updateParticles()
        this.drawParticles()
        this.animationId = requestAnimationFrame(this.animate)
      } catch (error) {
        this.handleCanvasError(error)
      }
    },
    
    // 检测 Canvas 支持
    detectCanvasSupport() {
      try {
        const testCanvas = document.createElement('canvas')
        const testCtx = testCanvas.getContext('2d')
        
        if (!testCanvas || !testCtx) {
          this.canvasSupported = false
          return
        }
        
        // 测试基本绘制功能
        testCtx.fillStyle = '#000'
        testCtx.fillRect(0, 0, 1, 1)
        
        this.canvasSupported = true
      } catch (error) {
        this.canvasSupported = false
        this.canvasErrorMessage = error.message
      }
    },
    
    // 处理 Canvas 错误
    handleCanvasError(error) {
      console.warn('Canvas 渲染出现错误，切换到降级方案:', error)
      this.hasCanvasError = true
      this.canvasErrorMessage = error.message
      
      // 停止动画
      if (this.animationId) {
        cancelAnimationFrame(this.animationId)
        this.animationId = null
      }
      
      // 清理事件监听器
      window.removeEventListener('resize', this.handleResize)
      window.removeEventListener('mousemove', this.handleMouseMove)
      
      // 初始化降级背景
      this.initFallbackBackground()
    },
    
    // 初始化降级背景
    initFallbackBackground() {
      this.generateStaticParticles()
    },
    
    // 生成静态粒子数据
    generateStaticParticles() {
      this.staticParticles = []
      for (let i = 0; i < this.fallbackParticleCount; i++) {
        this.staticParticles.push({
          x: Math.random() * 100,
          y: Math.random() * 100,
          size: Math.random() * 3 + 1,
          opacity: Math.random() * 0.6 + 0.2,
          color: this.getRandomFallbackColor(),
          animationDelay: Math.random() * 2
        })
      }
    },
    
    // 获取静态粒子样式
    getStaticParticleStyle(index) {
      const particle = this.staticParticles[index - 1]
      if (!particle) return {}
      
      return {
        left: particle.x + '%',
        top: particle.y + '%',
        width: particle.size + 'px',
        height: particle.size + 'px',
        opacity: particle.opacity,
        backgroundColor: particle.color,
        animationDelay: particle.animationDelay + 's'
      }
    },
    
    // 获取降级方案的随机颜色
    getRandomFallbackColor() {
      const colors = [
        '#667eea',
        '#764ba2',
        '#f093fb',
        '#f5576c',
        '#4facfe',
        '#00f2fe'
      ]
      return colors[Math.floor(Math.random() * colors.length)]
    }
  }
}
</script>

<style scoped>
.particle-container {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 0;
}

.particle-canvas {
  width: 100%;
  height: 100%;
  display: block;
}

/* 降级背景样式 */
.fallback-background {
  width: 100%;
  height: 100%;
  position: relative;
  background: var(--primary-gradient, linear-gradient(135deg, #667eea 0%, #764ba2 100%));
  opacity: 0.1;
  overflow: hidden;
}

.fallback-background.error-state {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  opacity: 0.05;
}

/* 静态粒子容器 */
.static-particles {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

/* 静态粒子样式 */
.static-particle {
  position: absolute;
  border-radius: 50%;
  animation: staticFloat 6s ease-in-out infinite;
  box-shadow: 0 0 10px currentColor;
}

.static-particle:nth-child(2n) {
  animation-direction: reverse;
  animation-duration: 8s;
}

.static-particle:nth-child(3n) {
  animation-duration: 10s;
  animation-delay: 1s;
}

.static-particle:nth-child(4n) {
  animation-duration: 7s;
  animation-delay: 0.5s;
}

.static-particle:nth-child(5n) {
  animation-duration: 9s;
  animation-delay: 1.5s;
}

/* 静态粒子浮动动画 */
@keyframes staticFloat {
  0%, 100% {
    transform: translateY(0px) translateX(0px) scale(1);
    opacity: 0.3;
  }
  25% {
    transform: translateY(-20px) translateX(10px) scale(1.1);
    opacity: 0.6;
  }
  50% {
    transform: translateY(-10px) translateX(-15px) scale(0.9);
    opacity: 0.4;
  }
  75% {
    transform: translateY(-30px) translateX(5px) scale(1.05);
    opacity: 0.7;
  }
}

/* Canvas 错误信息样式 */
.canvas-error-info {
  position: absolute;
  bottom: 20px;
  right: 20px;
  background: rgba(0, 0, 0, 0.8);
  color: white;
  padding: 12px 16px;
  border-radius: 8px;
  font-size: 12px;
  max-width: 300px;
  backdrop-filter: blur(10px);
  border: 1px solid rgba(255, 255, 255, 0.1);
  z-index: 1000;
}

.canvas-error-info p {
  margin: 0 0 4px 0;
  font-weight: 500;
}

.canvas-error-info small {
  opacity: 0.7;
  font-size: 10px;
  word-break: break-word;
}

/* 响应式设计 */
@media (max-width: 768px) {
  .static-particle {
    animation-duration: 4s;
  }
  
  .canvas-error-info {
    bottom: 10px;
    right: 10px;
    left: 10px;
    max-width: none;
    font-size: 11px;
  }
}

/* 减少动画偏好设置支持 */
@media (prefers-reduced-motion: reduce) {
  .static-particle {
    animation: none;
  }
  
  .fallback-background {
    opacity: 0.05;
  }
}

/* 高对比度模式支持 */
@media (prefers-contrast: high) {
  .fallback-background {
    opacity: 0.2;
  }
  
  .static-particle {
    box-shadow: 0 0 5px currentColor;
  }
  
  .canvas-error-info {
    background: rgba(0, 0, 0, 0.95);
    border: 2px solid white;
  }
}
</style>